package org.gridgain.internal.h2.vector.tx;

import org.gridgain.internal.h2.mvstore.tx.TransactionStore;
import org.gridgain.internal.h2.value.VersionedValue;
import org.gridgain.internal.h2.vector.MyMVMap;

public class MyCommitDecisionMaker extends MyMVMap.DecisionMaker<VersionedValue> {

    private long undoKey;
    private MyMVMap.Decision decision;

    void setUndoKey(long undoKey) {
        this.undoKey = undoKey;
        reset();
    }

    @Override
    public MyMVMap.Decision decide(VersionedValue existingValue, VersionedValue providedValue) {
        if (existingValue == null ||
                // map entry was treated as already committed, and then
                // it has been removed by another transaction (committed and closed by now)
                existingValue.getOperationId() != undoKey) {
            // this is not a final undo log entry for this key,
            // or map entry was treated as already committed and then
            // overwritten by another transaction
            // see TxDecisionMaker.decide()

            decision = MyMVMap.Decision.ABORT;
        } else /* this is final undo log entry for this key */ if (existingValue.getCurrentValue() == null) {
            decision = MyMVMap.Decision.REMOVE;
        } else {
            decision = MyMVMap.Decision.PUT;
        }
        return decision;
    }

    @Override
    public VersionedValue selectValue(VersionedValue existingValue, VersionedValue providedValue) {
        assert decision == MyMVMap.Decision.PUT;
        assert existingValue != null;
        return MyVersionedValueCommitted.getInstance(existingValue.getCurrentValue());
    }

    @Override
    public void reset() {
        decision = null;
    }

    @Override
    public String toString() {
        return "commit " + TransactionStore.getTransactionId(undoKey);
    }
}
